package net.doglog;

import java.util.*;

import javax.jdo.*;

import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
import com.google.appengine.api.users.UserService;
import com.google.appengine.api.users.UserServiceFactory;

public final class PostUtil {

	public static String formatDate(Date date) {
		return Blog.df.format(date);
	}

	public static String formatTime(long time) {
		return formatDate(new Date(time));
	}
	
	public static String formatTags(Set<String> tags) {
		StringBuilder sb = new StringBuilder();
		sb.append("<ul class=\"tags\">");
		for (String tag : tags)
			sb.append("<li><a href=\"/tag/" + tag + "\">" + tag + "</a></li>");
		sb.append("</ul>");
		return sb.toString();
	}
	
	public static String formatTagsPlain(Set<String> tags) {
		StringBuilder sb = new StringBuilder();
		boolean first = true;
		for (String tag : tags) {
			if (first) first = false;
			else sb.append(',');
			sb.append(tag);
		}
		return sb.toString();
	}

	public static boolean savePost(Post post) {
		boolean result = true;
		PersistenceManager pm = PMF.pm();
		Transaction tx = pm.currentTransaction();
		try {
			tx.begin();
			pm.makePersistent(post);
			tx.commit();
		} catch (JDOException e) {
			e.printStackTrace();
			result = false;
		} finally {
			if (tx.isActive())
				tx.rollback();
			pm.close();
		}
		return result;
	}

	public static Post getPost(long postId) {
		if (postId <= 0) return null;
		Post post = null;
		PersistenceManager pm = PMF.pm();
		try {
			Key key = KeyFactory.createKey(Post.class.getSimpleName(), postId);
			post = pm.getObjectById(Post.class, key);
			post = pm.detachCopy(post);
		} catch (JDOObjectNotFoundException e) {
			//post = null;
		} catch (JDOException e) {
			e.printStackTrace();
		} finally {
			pm.close();
		}
		return post;
	}

	@SuppressWarnings("unchecked")
	public static List<Post> getAllPosts() {
		List<Post> posts = null;
		PersistenceManager pm = PMF.pm();
		Query query = pm.newQuery(Post.class);
		query.setOrdering("time desc");
		try {
			posts = (List<Post>) query.execute();
			posts = (List<Post>) pm.detachCopyAll(posts);
		} catch (JDOException e) {
			posts = new ArrayList<Post>();
		} finally {
			query.closeAll();
			pm.close();
		}
		assert posts != null;
		return posts;
	}

	@SuppressWarnings("unchecked")
	public static List<Post> getPostsByTag(String tag) {
		List<Post> posts = null;
		PersistenceManager pm = PMF.pm();
		Query query = pm.newQuery(Post.class);
		query.setOrdering("time desc");
		query.setFilter("tags == tagParam");
		query.declareParameters("String tagParam");
		try {
			posts = (List<Post>) query.execute(tag);
			posts = (List<Post>) pm.detachCopyAll(posts);
		} catch (JDOException e) {
			posts = new ArrayList<Post>();
		} finally {
			query.closeAll();
			pm.close();
		}
		assert posts != null;
		return posts;
	}

	public static Comment newComment(Post post, String parent, String speaker, String content) throws Throwable {
		if (post == null)
			throw new Throwable(Blog.errorNoPostFound);
		if (speaker == null || speaker.trim().length() == 0)
			throw new Throwable(Blog.errorCommentSpeakerEmpty);
		if (content == null || content.trim().length() == 0)
			throw new Throwable(Blog.errorCommentContentEmpty);
		
		if (speaker.equals(Blog.author)) {
			UserService userService = UserServiceFactory.getUserService();
			if (userService.isUserLoggedIn()) {
				if (!userService.isUserAdmin())
					throw new Throwable(Blog.errorCommentSpeakerNotAllowed);
			} else {
				String loginURL = userService.createLoginURL("/post/" + post.getId() + "#comment");
				throw new Throwable("这个名字是管理员专用，请先<a href=\"" + loginURL + "\">登录</a>或换个名字。");
			}
		}

		/*
		 * Here is an example from GAE documentation.
		 * 
			KeyFactory.Builder keyBuilder = new KeyFactory.Builder(Customer.class.getSimpleName(), "custid985135");
			keyBuilder.addChild(AccountInfo.class.getSimpleName(), "acctidX142516");
			Key key = keyBuilder.getKey();

			AccountInfo acct = new AccountInfo();
			acct.setKey(key);
			pm.makePersistent(acct);
		 * 
		 * See: http://code.google.com/intl/zh-CN/appengine/docs/java/datastore/transactions.html
		 */
		Key parentKey = null;
		if (parent != null && parent.trim().length() > 0)
			parentKey = KeyFactory.stringToKey(parent.trim());
		Comment comment = new Comment(post, parentKey, speaker.trim(), content.trim());
		
		PersistenceManager pm = PMF.pm();
		Transaction tx = pm.currentTransaction();
		try {
			tx.begin();
			pm.makePersistent(comment);
			tx.commit();
		} finally {
			if (tx.isActive())
				tx.rollback();
			pm.close();
		}
		return comment;
	}

	public static Post newPost(String title, String content, String tags) throws Throwable {
		if (title == null || title.trim().length() == 0)
			throw new Throwable(Blog.errorPostTitleEmpty);
		if (content == null || content.trim().length() == 0)
			throw new Throwable(Blog.errorPostContentEmpty);
		
		Post post = new Post();
		post.setTitle(title);
		post.setContent(content);
		for (String tag : tags.split(","))
			post.addTag(tag);
		
		PersistenceManager pm = PMF.pm();
		Transaction tx = pm.currentTransaction();
		try {
			tx.begin();
			pm.makePersistent(post);
			tx.commit();
		} finally {
			if (tx.isActive())
				tx.rollback();
			pm.close();
		}
		return post;
	}

	public static void updatePost(Post post, String title, String content, String tags) throws Throwable {
		if (post == null)
			throw new Throwable(Blog.errorNoPostFound);
		if (title == null || title.trim().length() == 0)
			throw new Throwable(Blog.errorPostTitleEmpty);
		if (content == null || content.trim().length() == 0)
			throw new Throwable(Blog.errorPostContentEmpty);
		
		post.setTitle(title);
		post.setContent(content);
		post.clearTags();
		for (String tag : tags.split(","))
			post.addTag(tag);

		PersistenceManager pm = PMF.pm();
		Transaction tx = pm.currentTransaction();
		try {
			tx.begin();
			pm.makePersistent(post);
			tx.commit();
		} finally {
			if (tx.isActive())
				tx.rollback();
			pm.close();
		}
	}
}
